<script setup>
import {routes} from "@/router/routes.js";
import {convertRoutesToMenuPermissionTree, filterRoutesByPermission} from "@/utils/index.js";
import {useUserStore} from "@/store/user/index.js";
import {NCheckbox, NCheckboxGroup, NSpace, NSwitch} from "naive-ui";
import {h} from 'vue'

const userStore = useUserStore()
const emit = defineEmits(['on-change'])
const cascadeActive = ref(false)
const props = defineProps({
  // 初始值
  defaultValue: {
    type: Array,
    default: () => []
  }
})

const permissionTableData = computed(() => {
  const permissions = userStore.permissionList
  const validRoutes = filterRoutesByPermission(routes, permissions)
  return convertRoutesToMenuPermissionTree(validRoutes)
})

// 保存每个行已选中的 actions
const rowActionChecked = ref({})
const columns = [
  {
    type: 'selection',
  },
  {
    title: () => {
      return h(
          NSpace,
          null,
          {
            default: () => [
              '名称',
              h(
                  NSwitch,
                  {
                    size: 'small',
                    checked: cascadeActive.value,
                    'on-update:value': (val) => {
                      cascadeActive.value = val
                      rowActionChecked.value = {}
                      checkedKeys.value = []
                      updateChecks()
                    }
                  },
                  {
                    checked: () => '级联',
                    unchecked: () => '非级联'
                  }
              )
            ]
          }
      )
    },
    key: 'name',
    width: 200,
  },
  {
    title: '操作权限',
    key: 'actions',
    render(row) {
      const actions = Object.entries(row.actions || {})
      if (actions.length === 0) return null
      return h(
          NCheckboxGroup,
          {
            disabled: !checkedKeys.value.includes(row.permission),
            value: rowActionChecked.value[row.permission] || [],
            'on-update:value': (val) => {
              rowActionChecked.value[row.permission] = val
              updateChecks()
            }
          },
          {
            default: () =>
                actions.map(([actionKey, actionVal]) =>
                    h(NCheckbox, {value: actionVal, label: actionKey})
                )
          }
      )
    }
  }
]


function fillMenuKeys(menus, permissions, permissionResult) {
  menus.forEach(row => {
    if (permissions.includes(row.permission)) {
      permissionResult.push(row.permission)
      if (row.children && row.children.length) {
        fillMenuKeys(row.children, permissions, permissionResult)
      }
    }
  })
}

function fillActionKeys(menus, permissions, actionMap) {
  menus.forEach(row => {
    if (row.actions) {
      const actionKeys = Object.values(row.actions).filter(action => permissions.includes(action))
      if (actionKeys.length) {
        actionMap[row.permission] = actionKeys
      }
    }
    if (row.children && row.children.length) {
      fillActionKeys(row.children, permissions, actionMap)
    }
  })
}

const checkedKeys = ref([])

function handleCheck(keys) {
  checkedKeys.value = keys
  updateChecks()
}

const updateChecks = () => {
  const checkedActionKeys = Object.values(rowActionChecked.value).flat()
  const keys = Array.from(new Set([...checkedKeys.value, ...checkedActionKeys]))
  emit('on-change', keys)
}

// 初始化选中值
const initialValue = () => {
  if (!props.defaultValue || props.defaultValue.length === 0) {
    checkedKeys.value = []
    rowActionChecked.value = {}
    return
  }
  const menuKeys = []
  const actionMap = {}

  fillMenuKeys(permissionTableData.value, props.defaultValue, menuKeys)
  fillActionKeys(permissionTableData.value, props.defaultValue, actionMap)

  checkedKeys.value = menuKeys
  rowActionChecked.value = actionMap
}

watch(() => props.defaultValue, () => {
  initialValue()
}, {immediate: true})


defineExpose({
  initialValue
})

</script>

<template>
  <n-space vertical>
    <n-data-table
        :cascade="cascadeActive"
        :columns="columns"
        :data="permissionTableData"
        :row-key="row => row.permission"
        checkable
        :checked-row-keys="checkedKeys"
        @update:checked-row-keys="handleCheck"
        default-expand-all
    />
  </n-space>
</template>

<style scoped>

</style>